﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using TmxLib;

namespace TmxEditor
{
    class AsyncPreview
    {
        public interface ICommitCallback
        {
            void Commit(TmxUiComponent tmxUiComponent, TmxImage tmx, string snapshotFullName);
            void Abort(Exception exception);
        }

        private TmxUiComponent _tmxUiComponent;
        private TmxImage _tmx;
        private string _snapshotFullName;
        private ICommitCallback _callback;


        public AsyncPreview(TmxUiComponent tmxUiComponent, TmxImage tmx, string snapshotFullName, ICommitCallback callback)
        {
            _tmxUiComponent = tmxUiComponent;
            _tmx = tmx;
            _snapshotFullName = snapshotFullName;
            _callback = callback;
        }

        public void Run()
        {
            Thread thread = new Thread(ThreadProc);
            thread.Priority = ThreadPriority.BelowNormal;
            thread.IsBackground = false;
            thread.Start();

            
            return;

/*
            RunMethodDelegate d = new RunMethodDelegate(RunSync);
            AsyncCallback cb = new AsyncCallback(EndMethod);
            MethodState state = new MethodState(d, callback, tmxUiComponent, tmx, snapshotFullName);
            IAsyncResult asyncResult = d.BeginInvoke(tmxUiComponent, tmx, snapshotFullName, cb, state);
            return;
*/
        }

        void ThreadProc()
        {
            try
            {
                ReturnState ret = RunSync(_tmxUiComponent, _tmx, _snapshotFullName);
                _callback.Commit(_tmxUiComponent, _tmx, _snapshotFullName);
            }
            catch (Exception ex)
            {
                _callback.Abort(ex);
            }
        }

        private void EndMethod(IAsyncResult result)
        {
            MethodState state = (MethodState)result.AsyncState;
            ICommitCallback callback = state.Callback;
            try
            {
                ReturnState ret = state.Delegate.EndInvoke(result);
                callback.Commit(state.TmxUiComponent, state.Tmx, state.SnapshotFullName);
            }
            catch (Exception ex)
            {
                callback.Abort(ex);
            }
        }


        private delegate ReturnState RunMethodDelegate(TmxUiComponent tmxUiComponent, TmxImage tmx, string snapshotFullName);

        private ReturnState RunSync(TmxUiComponent tmxUiComponent, TmxImage tmx, string snapshotFullName)
        {
            SnapshotInfo snapshot = SnapshotInfo.Create(snapshotFullName);
            if (snapshot.HasManifest)
            {
                SnapshotBinaryItemInfo assemblyInfo;
                SnapshotType typeInfo;
                if (snapshot.FindType(tmxUiComponent.Context, out assemblyInfo, out typeInfo))
                {
                    snapshot.Extract();
                    snapshot.Build();
                    snapshot.RunPreview(assemblyInfo.AssemblyName, typeInfo.Name);
                }

                return new ReturnState();
            }

            else
                throw new Exception("Could not found Preview Shapshot Manifest at " + snapshotFullName);

        }

        class MethodState
        {
            public readonly RunMethodDelegate Delegate;
            public readonly ICommitCallback Callback;
            public readonly TmxUiComponent TmxUiComponent;
            public readonly TmxImage Tmx;
            public readonly string SnapshotFullName;


            public MethodState(RunMethodDelegate @delegate, ICommitCallback callback, TmxUiComponent tmxUiComponent, TmxImage tmx, string snapshotFullName)
            {
                Delegate = @delegate;
                Callback = callback;
                TmxUiComponent = tmxUiComponent;
                Tmx = tmx;
                this.SnapshotFullName = snapshotFullName;
            }
        }

        class ReturnState
        {


        }
    }
}


